﻿using FastCloud.Base.Config;
using FastIOC.Attribute;
using FastORM.Entity;
using FastORM.Handle;
using FastORM.Mapping;
using FastUtil.Config;
using FastUtil.Convert;
using FastUtil.Extra;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace FastCloud.Base.Desgin
{
    public class BaseCacheML<TEntity> : BaseML<TEntity> where TEntity : BaseEntity
    {
        public string TableCacheKey { set; get; }
        public BaseCacheML()
        {
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            TableCacheKey = mapper.TableName;
        }

        public void InitCache()
        {
            CommonDTO BaseDTO = new CommonDTO();
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            List<TEntity> DBEntityList = BaseDTO.Select<TEntity>(mapper.TableName, "*", "1=1", "");
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.DelteKey(TableCacheKey, CloudUtil.GetRedisCacheDBNum());
                foreach (TEntity Entity in DBEntityList)
                {
                    string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
                }
            }
            else
            {
                RedisUtil.DelteKey(TableCacheKey, Execute, CloudUtil.GetRedisCacheDBNum());
                foreach (TEntity Entity in DBEntityList)
                {
                    string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute, CloudUtil.GetRedisCacheDBNum());
                }
            }

        }

        public void ClearCache()
        {
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.DelteKey(TableCacheKey, CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.DelteKey(TableCacheKey, Execute, CloudUtil.GetRedisCacheDBNum());
            }

        }

        public override void Insert(TEntity Entity)
        {
            base.Insert(Entity);
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute, CloudUtil.GetRedisCacheDBNum());
            }

        }

        public override void InsertBatch(List<TEntity> EntityList)
        {
            base.InsertBatch(EntityList);
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            IBatch Execute = GetBatchExecute();

            foreach (TEntity Entity in EntityList)
            {
                string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
                if (Execute == null)
                {
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
                }
                else
                {
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute, CloudUtil.GetRedisCacheDBNum());
                }

            }
        }

        public override void DeleteByID(string UnitGuid)
        {
            base.DeleteByID(UnitGuid);
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.DelteHash(TableCacheKey, UnitGuid, CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.DelteHash(TableCacheKey, UnitGuid, Execute, CloudUtil.GetRedisCacheDBNum());
            }

        }

        public override void DeleteByFiled(string FieldName, string FiledValue)
        {
            base.DeleteByFiled(FieldName, FiledValue);
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.DelteKey(TableCacheKey, CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.DelteKey(TableCacheKey, Execute, CloudUtil.GetRedisCacheDBNum());
            }
        }

        public override void DeleteBatch(List<string> UnitGuidList)
        {
            base.DeleteBatch(UnitGuidList);
            IBatch Execute = GetBatchExecute();
            foreach (string UnitGuid in UnitGuidList)
            {
                if (Execute == null)
                {
                    RedisUtil.DelteHash(TableCacheKey, UnitGuid, CloudUtil.GetRedisCacheDBNum());
                }
                else
                {
                    RedisUtil.DelteHash(TableCacheKey, UnitGuid, Execute, CloudUtil.GetRedisCacheDBNum());
                }
            }
        }

        public override void UpdateByID(TEntity Entity)
        {
            base.UpdateByID(Entity);
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
            IBatch Execute = GetBatchExecute();
            if (Execute==null)
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute,CloudUtil.GetRedisCacheDBNum());
            }
            
        }

        public override void UpdateByFieldName(TEntity Entity, string FieldName)
        {
            base.UpdateByFieldName(Entity, FieldName);
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
            IBatch Execute = GetBatchExecute();
            if (Execute == null)
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
            }
            else
            {
                RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute, CloudUtil.GetRedisCacheDBNum());
            }
             
        }

        public override void UpdateBatch(List<TEntity> EntityList)
        {
            base.UpdateBatch(EntityList);
            MapperEntity mapper = StructMapping.GetInstance().GetMapperEntity(typeof(TEntity));
            IBatch Execute = GetBatchExecute();
            foreach (TEntity Entity in EntityList)
            {
                string RowGuid = ValueConvert.ConvertToString(mapper.GetKeyValue(Entity));
                if (Execute == null)
                {
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), CloudUtil.GetRedisCacheDBNum());
                }
                else
                {
                    RedisUtil.SetHash(TableCacheKey, RowGuid, JsonConvert.SerializeObject(Entity), Execute,CloudUtil.GetRedisCacheDBNum());
                }
                  
            }

        }

        public override TEntity SelectOne(string UnitGuid)
        {
            string result = RedisUtil.GetHash(TableCacheKey, UnitGuid, CloudUtil.GetRedisCacheDBNum());
            if (!string.IsNullOrEmpty(result))
            {
                return JsonConvert.DeserializeObject<TEntity>(result);
            }
            else
            {
                return base.SelectOne(UnitGuid);
            }
        }


        public IBatch GetBatchExecute()
        {
            string RootThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
            LocalTransaction LT = TransitionManage.GetTransition(RootThreadID);
            if (LT != null)
            {
                return LT.CacheTransition.BatchExecute;
            }
            else
            {
                return null;
            }

        }

    }
}
